package main

import "fmt"

type Widget struct {
	X, Y int
}

type Label struct {
	Widget
	Text string
}

type Button struct {
	Label
}

type ListBox struct {
	Widget
	Texts []string
	Index int
}

type Painter interface {
	Paint()
}

type Clicker interface {
	Click()
}

func (label Label) Paint() {
	fmt.Printf("%p:Label.Paint(%q)\n", &label, label.Text)
}

func (button Button) Paint() { // Button 覆盖了 Label
	fmt.Printf("Button.Paint(%s)\n", button.Text)
}

func (listBox ListBox) Paint() {
	fmt.Printf("ListBox.Paint(%q)\n", listBox.Texts)
}

func (listBox ListBox) Click() {
	fmt.Printf("ListBox.Click(%q)\n", listBox.Texts)
}

func main() {
	label := Label{Widget{10, 10}, "State:"}
	label.X = 11
	label.Y = 12

	button1 := Button{Label{
		Widget: Widget{10, 70},
		Text:   "OK",
	}}
	button2 := Button{Label{
		Widget: Widget{50, 70},
		Text:   "Cancel",
	}}
	listBox := ListBox{
		Widget: Widget{10, 40},
		Texts:  []string{"AL", "AK", "AZ", "AR"},
		Index:  0,
	}

	for _, painter := range []Painter{label, listBox, button1, button2} {
		painter.Paint()
	}

	for _, widget := range []interface{}{label, listBox, button1, button2} {
		widget.(Painter).Paint()
		if clicker, ok := widget.(Clicker); ok {
			clicker.Click()
		}
		fmt.Println()
	}
}
